package edu.gatech.cs4400.spring2014.A8.control;

import java.sql.ResultSet;
import java.sql.SQLException;

import edu.gatech.cs4400.spring2014.A8.model.ReadQuery;
import edu.gatech.cs4400.spring2014.A8.view.ApplicationWindow;
import edu.gatech.cs4400.spring2014.A8.view.LoginPanel;
import edu.gatech.cs4400.spring2014.A8.view.RegistrationPanel;

/**
 * Controller to execute the login sequence.
 * 
 * @author Stephen
 */
public class LoginController implements Controller {
	/**
	 * Execute the login sequence. Will loop until user enters a valid username 
	 *  and password. Users can register new accounts from here.
	 */
	public void run() {
		//set up the login panel
		LoginPanel panel = new LoginPanel();
		ApplicationWindow.addView(panel, "LoginScreen");
		ApplicationWindow.setView("LoginScreen");
		
		//until the user enters a valid username/password combination, loop
		while (true) {
			//wait for the user to press a button on the panel
			Waiter.waitFor(panel);
			//interpret the feedback
			if (panel.feedback == LoginPanel.Feedback.LOGIN) {
				//check the login information against the database
				LoginValidationQuery lvq = new LoginValidationQuery(panel.getUsername(), panel.getPassword());
				if (lvq.isValid()) {
					//if it's valid, kick out of the login sequence
					panel.setMessage("Login accepted!"); //$$$
					Session.setActiveAccount(panel.getUsername(), lvq.getAccountType());
					return;
				}
				else {
					//if it's invalid, notify the user and reset the GUI
					panel.reset();
					panel.setMessage(String.format("Login failed for '%s', '%s'", panel.getUsername(), panel.getPassword()));
				}
			}
			else if (panel.feedback == LoginPanel.Feedback.REGISTER) {
				//run the registration procedure
				RegistrationController rc = new RegistrationController();
				rc.run();
				panel.reset();
				if (rc.getFeedback() == RegistrationPanel.Feedback.REGISTER) {
					//registration means automatic login
					return;
				}
				//set the view back to the login screen
				ApplicationWindow.setView("LoginScreen");
			}
		}
	}
	
	/**
	 * Query wrapper to check the validity of login credentials
	 * @author Stephen
	 */
	private class LoginValidationQuery extends ReadQuery{
		private boolean valid;
		private String accountType;
		
		/**
		 * Build the query using the username and password received from the user
		 * @param username
		 * @param password
		 */
		public LoginValidationQuery(String username, String password) {
			sql = String.format("SELECT Username, AccountType FROM Users WHERE Username='%s' AND Password='%s';", username, password);
			valid = false;
			accountType = null;
		}

		/**
		 * Interpret the results of the SQL query
		 * 0 results from the query indicates an invalid login
		 * 1 result indicates a valid login
		 * >1 results means a terrible, horrible error
		 */
		@Override
		protected void parseResult(ResultSet rs) throws SQLException{
			if (!rs.next()) { //empty result
				valid = false;
			}
			else if (rs.isFirst() && rs.isLast()) { //1 element in the result
				valid = true;
				accountType = rs.getString(2);
			}
			else { 
				throw new SQLException("Login query returned multiple results.");
			}
		}
		
		/**
		 * Determine the validity of the given username/password combination
		 * Run the SQL query if needed
		 * @return
		 */
		public boolean isValid() {
			boolean result;
			if (!executed && !failed) {
				execute();
				if (!failed) {
					result = valid;
				}
				else {
					result = false;
				}
			}
			else {
				result = valid;
			}
			return result;
		}
		
		/**
		 * Get the account type information from the result
		 * 
		 * @return
		 */
		public String getAccountType() {
			return accountType;
		}
	}
}
